首先要在 Info.plist 加入相機使用權限,新增privacy-camera usage description
在 Main.Storyboard 拉個 view 和 button
回到 View Controller import AVFoundation(控制視聽設備、相機、影音等)及SafariServices(在App中使用Safari開啟網頁)
AVCaptureMetadataOutputObjectsDelegate:用來捕捉並輸出數據的方法。
UINavigationControllerDelegate:彈出視窗,並可返回上一頁(就是代理NavigationController),在此是彈出相簿視窗。
再來使用AVCaptureSession(用於捕捉視訊及音訊,協調視訊及音訊的輸入及輸出)、AVCaptureVideoPreviewLayer(呈現Session捕捉的資料)
viewDidAppear 在完成視圖的初始外觀中涉及的所有圖形和動畫之後,將調用此方法
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setQRCodeScan()
}
//掃QRCode的動作
func setQRCodeScan(){
//實體化一個AVCaptureSession物件
captureSesion = AVCaptureSession()
//AVCaptureDevice可以抓到相機和其屬性
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {return}
let videoInput:AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
}catch let error {
print(error)
return
}
if (captureSesion?.canAddInput(videoInput) ?? false ){
captureSesion?.addInput(videoInput)
}else{
return
}
//AVCaptureMetaDataOutput輸出影音資料,先實體化AVCaptureMetaDataOutput物件
let metaDataOutput = AVCaptureMetadataOutput()
if (captureSesion?.canAddOutput(metaDataOutput) ?? false){
captureSesion?.addOutput(metaDataOutput)
//關鍵!執行緒處理QRCode
metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
//metadataOutput.metadataObjectTypes表示要處理哪些類型的資料,處理QRCODE
metaDataOutput.metadataObjectTypes = [.qr, .ean8 , .ean13 , .pdf417]
}else{
return
}
//用AVCaptureVideoPreviewLayer來呈現Session上的資料
previewLayer = AVCaptureVideoPreviewLayer(session: captureSesion!)
//顯示size
previewLayer.videoGravity = .resizeAspectFill
//呈現在camView上面
previewLayer.frame = camView.layer.frame
//加入畫面
view.layer.addSublayer(previewLayer)
//開始影像擷取呈現鏡頭的畫面
captureSesion?.startRunning()
}
接著使用AVCaptureMetadataOutput物件辨識QRCode
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutputmetadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
captureSesion?.startRunning()
if let metadataObject = metadataObjects.first{
//AVMetadataMachineReadableCodeObject是從OutPut擷取到barcode內容
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else {return}
//將讀取到的內容轉成string
guard let stringValue = readableObject.stringValue else {return}
//掃到QRCode後的震動提示
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
//存取QRcodeURL
QRCodeString = stringValue
}
}
按下Button後利用present以safari開啟Label上顯示的URL:
//開啟網頁
@IBAction func openWebButton(_ sender: Any) {
let url = URL(string:QRCodeString)
let safariVC = SFSafariViewController(url: url!)
present(safariVC,animated: true ,completion: nil)
}